#include <QDebug>
#include "astng/Scopes/ModuleScope.h"
#include "PyHighlighter.h"

PyHighlighter::PyHighlighter(ModuleScope *scope, QTextDocument * parent):
    QSyntaxHighlighter(parent),
    _scope(scope)
{
    QTextCharFormat keyFormat;
    keyFormat.setForeground(QColor(42, 255, 5));

    QStringList keyws = QStringList() << "\\breturn\\b" << "\\bfor\\b" << "\\bif\\b" << "\\bwith\\b" << "\\byeld\\b"
              << "\\bpass\\b" << "\\btry\\b" << "\\bexcept\\b" << "\\bdelete\\b" << "\\braise\\b"
              << "\\bfinally\\b" << "\\bbreak\\b" << "\\bcontinue\\b" << "\\bdef\\b" << "\\bclass\\b";

    Rule rule;
    foreach(QString key, keyws){
        rule.pattern.setPattern(key);
        rule.format = keyFormat;
        _keywords.append(rule);
    }

    QTextCharFormat opFormat;
    opFormat.setForeground(QColor(245, 48, 255));

    QStringList ops = QStringList() << "\\bor\\b" << "\\band\\b" << "\\bnot\\b" << "\\bin\\b"
                                    << ">" << "<" << "==" << ">=" << "<=";

    foreach(QString key, ops){
        rule.pattern.setPattern(key);
        rule.format = opFormat;
        _keywords.append(rule);
    }

    _stringFormat.setForeground(QColor(255, 0, 0));
    _stringRex.setPattern("'|\"|(\"\"\")");
}

void PyHighlighter::highlightBlock(const QString &text)
{
    /*int state = previousBlockState();
    if (state == 1){
        //setFormat(0, text.length(), _stringFormat);
    }
    foreach(Rule r, _keywords){
        int index = r.pattern.indexIn(text);
        while(index >= 0){
            int length =  r.pattern.matchedLength();
            setFormat(index, length, r.format);
            index = r.pattern.indexIn(text, index+length);
        }
    }
    parseString("'", text, 1);
    parseString("\"", text, 2);
    parseString("\"\"\"", text, 3, true);*/
    /*
    bool start = state != 1;
    int len = 0;
    int sindex = _stringRex.indexIn(text);
    while(sindex >= 0){
        if (start){
            len = sindex;
            start = false;
        } else {
            setFormat(len, sindex - len + _stringRex.matchedLength(), _stringFormat);
            start = true;
        }
        sindex = _stringRex.indexIn(text, sindex + _stringRex.matchedLength());
    }*/

    //qDebug() << currentBlock().firstLineNumber() << text.length();
    //qDebug() << text << previousBlockState();
    if (previousBlockState()>0)
        setFormat(0, text.length(), *formatForState(previousBlockState()));

    for(int line = currentBlock().firstLineNumber(); line < currentBlock().firstLineNumber() + currentBlock().lineCount(); ++line){
        QList<SimpleNodePtr> ast = _scope->astInLine(line);
        if (!ast.length()){
            setCurrentBlockState(previousBlockState());
        } else {
            for(int i = 0; i < ast.length(); ++i){
                //setFormat(ast[i]->beginColumn-1, ast[i]->endColumn - ast[i]->beginColumn + 1, *formatForState(format(ast[i]->type())));
            }
            if (ast.last()->endLine > currentBlock().firstLineNumber()){
                //setCurrentBlockState(format(ast.last()->type()));
            } else {
                setCurrentBlockState(-1);
            }
        }
    }
}

void PyHighlighter::parseString(const QString& quote, const QString& text, int state, bool multiline)
{
    int found = previousBlockState() == state ? 0 : -1;
    bool needMultiline = true;
    int sindex = text.indexOf(quote);
    while(sindex >= 0){
        if (sindex > 0 && text[sindex-1] == '\\'){
            sindex = text.indexOf(quote, sindex + quote.length());
            continue;
        }
        if (found >= 0){
            setFormat(found, sindex - found + quote.length(), _stringFormat);
            found = -1;
            setCurrentBlockState(0);
            needMultiline = false;
        } else {
            found = sindex;
        }
        sindex = text.indexOf(quote, sindex + quote.length());
        if (multiline && previousBlockState() == state)
            needMultiline = false;
    }
    if (found >= 0){
        setFormat(found, (sindex > 0 ? sindex : text.length()) - found + quote.length(), _stringFormat);
        if (text.right(1) == "\\" || (multiline && needMultiline)){
            setCurrentBlockState(state);
            //rehighlightBlock(currentBlock().next());
        }
    }
}

int PyHighlighter::format(const QString& type)
{
    if (type == "Name" || type == "NameTok")
        return 1;
    if (type == "FunctionDef" || type == "Pass")
        return 2;
    if (type == "Str")
        return 3;
    if (type == "Num")
        return 4;
    return -1;
}



QTextCharFormat* PyHighlighter::formatForState(int state)
{
    static QHash<int, QTextCharFormat*> formats;
    if (!formats.count()){
        formats[-1] = new QTextCharFormat();
        formats[-1]->setForeground(Qt::white);

        formats[1] = new QTextCharFormat();
        formats[1]->setForeground(Qt::green);

        formats[2] = new QTextCharFormat();
        formats[2]->setForeground(Qt::blue);

        formats[3] = new QTextCharFormat();
        formats[3]->setForeground(Qt::red);

        formats[4] = new QTextCharFormat();
        formats[4]->setForeground(Qt::darkGreen);
    }
    return formats[state];
}
